package com.mystudy.concurrent.designModel.readWiriteModel;

/**
 * TODO: 读写锁
 *
 * @author acy
 * @since 2019/05/28 20:09
 */
public class MyReadWriteLock {
	//读线程数
	private int readingReaders = 0;
	//等待读的线程数
	private int waitingReaders = 0;
	//等待写的线程数
	private int waitingWriters = 0;
	//正在写的线程数
	private int writingWriters = 0;
	private boolean preferWriter = true;

	public MyReadWriteLock() {
		this(true);
	}

	public MyReadWriteLock(boolean preferWriter) {
		this.preferWriter = preferWriter;
	}

	/**
	 * 获取读锁
	 */
	public synchronized void readLock() {
		this.waitingReaders++;
		try {
			//如果有写线程在执行需要等待
			while (writingWriters > 0 || (preferWriter && writingWriters > 0)) {
				this.wait();
			}
			//拿到了锁就需要将正在读的线程+1
			this.readingReaders++;
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			//没有wait则减去
			this.waitingReaders--;
		}
	}

	/**
	 * 释放读锁
	 */
	public synchronized void readUnlock() {
		this.readingReaders--;
		this.notifyAll();
	}

	/**
	 * 写锁
	 */
	public synchronized void writeLock() {
		this.writingWriters++;
		try {
			//如果存在正在读的线程或者正在写的线程就需要等待
			while (readingReaders > 0 || writingWriters > 0) {
				this.wait();
			}
			//拿到了锁就正在写的线程+1
			this.writingWriters++;
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			this.waitingWriters--;
		}
	}

	/**
	 * 释放写锁
	 */
	public synchronized void UnWriteLock() {
		this.waitingWriters--;
		this.notifyAll();
	}
}
